// Contrôle la partie audio.


#ifndef LIGHT_AUDIO_H
#define LIGHT_AUDIO_H

#include <SDL_mixer.h>
#include <string>
#include "Light_Debug.h"

#define LIGHT_AUDIOMUTE 0
#define NONAME ""

const long int MaxTempSound=64;
const long int MaxPerSound=33; // +1 à cause de la variable i.

class Info_Audio{
	
  public:
  
    std::string name;
    bool Preloaded=false;
	
}; Info_Audio Light_AudioMetadata[MaxPerSound];

// La variable i est de 1 pour les sons persistants, parce que ça marche mieux.

class Play_Audio{
	
  public:
  
    int Sound(const char* file, std::string name="", int loops=0, int fadeout=0, int time=-1){ // std::string name sert à accéder aux sons persistant facilement.
		
	  for(int i=1;i<MaxPerSound;i++){ // Libère les sons persistants le plus possible.
		  
	    if(Mix_Playing(i)==0){ 
			
		  Mix_FreeChunk(PerSound[i]);
          PerSound[i]=NULL;
          Light_AudioMetadata[i].name.clear();
			
		}
		  
	  }
	  
	  if(Mix_Playing(0)==0){ // Libère les sons temporaires le plus possible, ça marche pour une raison inconnue.
	  
	    for(int i=0;i<MaxTempSound;i++){
			
		  Mix_FreeChunk(TempSound[i]);
          TempSound[i]=NULL;
			
	    }
	    
	  }
	  
	  if(loops<0){ // Détecté en tant que son persistant.
		  
		for(int i=1;i<MaxPerSound;i++){ // Vérifie le nom.
		
	      if(Light_AudioMetadata[i].name==name){
			
			Light_PrintDebug("Erreur Audio : Le nom est déjà pris !");
			return 1;
			  
		  }
			  	
		}
		  
	    for(int i=1;i<MaxPerSound;i++){
			
		  if(PerSound[i]==NULL){
			
			PerSound[i]=Mix_LoadWAV(file);
			
			if(Mix_FadeInChannelTimed(i, PerSound[i], loops, fadeout, time)==-1){
				
			  Light_PrintDebug("Erreur Audio : Le son persistant n'a pas pu être joué, peut être que tout les channels sont pris ?");
              Mix_FreeChunk(PerSound[i]);
              PerSound[i]=NULL;
              return 1;
				
			}

			Light_AudioMetadata[i].name=name;
		    i=MaxPerSound;
			  
		  }
			
		}
		  
	  }
	  
	  else{ // Sons temporaires.
		  
	    for(int i=0;i<MaxTempSound;i++){
			
		  if(TempSound[i]==NULL){
			
			TempSound[i]=Mix_LoadWAV(file);
			
			if(Mix_FadeInChannelTimed(-1, TempSound[i], loops, fadeout, time)==-1){
				
			  Light_PrintDebug("Erreur Audio : Le son temporaire n'a pas pu être joué, peut être que tout les channels sont pris ?");
              Mix_FreeChunk(TempSound[i]);
              TempSound[i]=NULL;
              return 1;
				
			}
			
		    i=MaxTempSound;
			  
		  }
			
		}
		  
	  }
	  	
	  return 0;
		
	}
	
	int Music(const char* file, int loops=-1, int fadeout=0, double pos=0){
	
	  if(Mix_PlayingMusic()!=0){
  
        Light_PrintDebug("Erreur Audio : Une musique est déjà en jeu.");
        return 1;
   
      }
      
      Mix_FreeMusic(gMusic);
      gMusic=Mix_LoadMUS(file);
      
      if(Mix_FadeInMusicPos(gMusic, loops, fadeout, pos)==-1){
  
        Light_PrintDebug("Erreur Audio : La musique n'a pas pu être joué.");
        Mix_FreeMusic(gMusic);
        return 1;
  
      }
	
	  return 0;
		
	}
  
  private:
  
    Mix_Chunk *TempSound[MaxTempSound]={NULL};
    Mix_Chunk *PerSound[MaxPerSound]={NULL};
    Mix_Music *gMusic=NULL;
	
}; Play_Audio Light_PlayAudio;

class Volume_Audio{
	
  public:
  
    void Sound(int volume){ // 0 à 128.
	
	  Mix_Volume(-1, volume);
		
	}
	
	void Music(int volume){
		
	  Mix_VolumeMusic(volume);
		
	}
	
}; Volume_Audio Light_SetVolume;

class Pause_Audio{
	
  public:
  
    void Sound(std::string name=""){
		
	  if(name==""){
		  
	    Mix_Pause(-1);
		
	  }
	
	  else{
		  
	    for(int i=1;i<MaxPerSound;i++){
		
	      if(Light_AudioMetadata[i].name==name){
		
		    Mix_Pause(i);
		    i=MaxPerSound;
			
		  }
		  
	    }
		
	  }
		
	}
	
	void Music(){
		
	  Mix_PauseMusic();
		
    }
	
}; Pause_Audio Light_PauseAudio;

class Resume_Audio{
	
  public:
  
    void Sound(std::string name=""){
		
	  if(name==""){
		  
	    Mix_Resume(-1);
		
	  }
	
	  else{
		  
	    for(int i=1;i<MaxPerSound;i++){
		
	      if(Light_AudioMetadata[i].name==name){
		
		    Mix_Resume(i);
		    i=MaxPerSound;
			
		  }
		  
	    }
		
	  }
		
	}
	
	void Music(){
		
	  Mix_ResumeMusic();
		
    }
	
}; Resume_Audio Light_ResumeAudio;

class Stop_Audio{
	
  public:
  
    void Sound(std::string name="", int fadeout=0){
		
	  if(name==""){
		  
	    Mix_FadeOutChannel(-1, fadeout);
		
	  }
	
	  else{
		  
	    for(int i=1;i<MaxPerSound;i++){
		
	      if(Light_AudioMetadata[i].name==name){
		
		    Mix_FadeOutChannel(i, fadeout);
		    i=MaxPerSound;
			
		  }
		  
	    }
		
	  }
		
	}
	
	void Music(int fadeout=0){
		
	  Mix_FadeOutMusic(fadeout);
		
	}
	
}; Stop_Audio Light_StopAudio;

class Effect_Audio{

  public:
  
    int Unregister(std::string name=""){
		
	  if(name==""){
		  
	    if(Mix_UnregisterAllEffects(-1)==0){
  
          Light_PrintDebug("Erreur Audio : Impossible d'enlever les effets des chunks !");
          return 1;
  
        }
		
	  }
	
	  else{
		  
	    for(int i=1;i<MaxPerSound;i++){
		
	      if(Light_AudioMetadata[i].name==name){
		
		    if(Mix_UnregisterAllEffects(i)==0){
  
              Light_PrintDebug("Erreur Audio : Impossible d'enlever les effets d'un chunk !");
              return 1;
  
            }
            
		    i=MaxPerSound;
			
		  }
		  
	    }
		
	  }
	  
	  return 0;
		
	}
	
	int ApplyPosition(std::string name="", Sint16 angle=1, Uint8 distance=1){ // Utiliser une distance et un angle de 0 enlèvera tout les effets du channel !
		
	  if(name==""){
		  
	    if(Mix_SetPosition(-1, angle, distance)==0){
  
          Light_PrintDebug("Erreur Audio : Impossible d'appliquer la position du son dans tout les channels !");
          return 1;
  
        }
		
	  }
	
	  else{
		  
	    for(int i=1;i<MaxPerSound;i++){
		
	      if(Light_AudioMetadata[i].name==name){
		
		    if(Mix_SetPosition(i, angle, distance)==0){
  
              Light_PrintDebug("Erreur Audio : Impossible d'appliquer la position du son dans un channel !");
              return 1;
  
            }
            
		    i=MaxPerSound;
			
		  }
		  
	    }
		
	  }	
		
	  return 0;
		
	}
	
}; Effect_Audio Light_AudioEffect;

#endif
